// Ожидать завершения выполнения процедуры в фоновом задании и открыть форму ожидания длительной операции.
// Применяется совместно с функцией ДлительныеОперации.ВыполнитьВФоне для повышения отзывчивости пользовательского 
// интерфейса, заменяя длительный серверный вызов на запуск фонового задания.
// 
// Параметры:
//  ДлительнаяОперация     - Структура - см. возвращаемое значение функции ДлительныеОперации.ВыполнитьВФоне.
//  ОповещениеОЗавершении  - ОписаниеОповещения - оповещение, которое вызывается при завершении фонового задания. 
//                           Параметры процедуры-обработчика оповещения: 
//   * Результат - Структура, Неопределено - структура со свойствами или Неопределено, если задание было отменено. Свойства: 
//	   ** Статус           - Строка - "Выполнено", если задание было успешно выполнено;
//	                                  "Ошибка", если задание завершено с ошибкой.
//	   ** АдресРезультата  - Строка - адрес временного хранилища, в которое будет
//	                                  помещен (или уже помещен) результат работы процедуры.
//	   ** АдресДополнительногоРезультата - Строка - если установлен параметр ДополнительныйРезультат, 
//	                                     содержит адрес дополнительного временного хранилища,
//	                                     в которое будет помещен (или уже помещен) результат работы процедуры.
//	   ** КраткоеПредставлениеОшибки   - Строка - краткая информация об исключении, если Статус = "Ошибка".
//	   ** ПодробноеПредставлениеОшибки - Строка - подробная информация об исключении, если Статус = "Ошибка".
//	   ** Сообщения        - ФиксированныйМассив, Неопределено - массив объектов СообщениеПользователю, 
//                                                сформированных в процедуре-обработчике длительной операции.
//   * ДополнительныеПараметры - Произвольный - произвольные данные, переданные в описании оповещения. 
//  ПараметрыОжидания      - Структура - см. ДлительныеОперацииКлиент.ПараметрыОжидания.
//
Процедура ОжидатьЗавершение(Знач ДлительнаяОперация, Знач ОповещениеОЗавершении = Неопределено,
	Знач ПараметрыОжидания = Неопределено) Экспорт

	ПроверитьПараметрыОжидатьЗавершение(ДлительнаяОперация, ОповещениеОЗавершении, ПараметрыОжидания);

	Если ДлительнаяОперация.Статус <> "Выполняется" Тогда
		Если ОповещениеОЗавершении <> Неопределено Тогда
			Если ДлительнаяОперация.Статус <> "Отменено" Тогда
				Результат = Новый Структура;
				Результат.Вставить("Статус", ДлительнаяОперация.Статус);
				Результат.Вставить("АдресРезультата", ДлительнаяОперация.АдресРезультата);
				Результат.Вставить("АдресДополнительногоРезультата", ДлительнаяОперация.АдресДополнительногоРезультата);
				Результат.Вставить("КраткоеПредставлениеОшибки", ДлительнаяОперация.КраткоеПредставлениеОшибки);
				Результат.Вставить("ПодробноеПредставлениеОшибки", ДлительнаяОперация.ПодробноеПредставлениеОшибки);
				Результат.Вставить("Сообщения", ?(ПараметрыОжидания <> Неопределено
					И ПараметрыОжидания.ВыводитьСообщения, ДлительнаяОперация.Сообщения, Неопределено));
			Иначе
				Результат = Неопределено;
			КонецЕсли;

			Если ДлительнаяОперация.Статус = "Выполнено" И ПараметрыОжидания <> Неопределено Тогда
				ПоказатьОповещение(ПараметрыОжидания);
			КонецЕсли;
			ВыполнитьОбработкуОповещения(ОповещениеОЗавершении, Результат);
		КонецЕсли;
		Возврат;
	КонецЕсли;

	ПараметрыФормы = ПараметрыОжидания(Неопределено);
	Если ПараметрыОжидания <> Неопределено Тогда
		ЗаполнитьЗначенияСвойств(ПараметрыФормы, ПараметрыОжидания);
	КонецЕсли;
	ПараметрыФормы.Вставить("АдресРезультата", ДлительнаяОперация.АдресРезультата);
	ПараметрыФормы.Вставить("АдресДополнительногоРезультата", ДлительнаяОперация.АдресДополнительногоРезультата);
	ПараметрыФормы.Вставить("ИдентификаторЗадания", ДлительнаяОперация.ИдентификаторЗадания);

	Если ПараметрыФормы.ВыводитьОкноОжидания Тогда
		ПараметрыФормы.Удалить("ФормаВладелец");

		ОткрытьФорму("ОбщаяФорма.УИ_ДлительнаяОперация", ПараметрыФормы, ?(ПараметрыОжидания <> Неопределено,
			ПараметрыОжидания.ФормаВладелец, Неопределено), , , , ОповещениеОЗавершении);
	Иначе
		ПараметрыФормы.Вставить("ОповещениеОЗавершении", ОповещениеОЗавершении);
		ПараметрыФормы.Вставить("ТекущийИнтервал", ?(ПараметрыФормы.Интервал <> 0, ПараметрыФормы.Интервал, 1));
		ПараметрыФормы.Вставить("Контроль", ТекущаяДата() + ПараметрыФормы.ТекущийИнтервал); // дата сеанса не используется

		Операции = АктивныеДлительныеОперации();
		Операции.Список.Вставить(ПараметрыФормы.ИдентификаторЗадания, ПараметрыФормы);

		ПодключитьОбработчикОжидания("УИ_КонтрольДлительныхОпераций", ПараметрыФормы.ТекущийИнтервал, Истина);
	КонецЕсли;

КонецПроцедуры

Функция АктивныеДлительныеОперации() Экспорт

	ИмяПараметра = "УИ_УниверсальныеИнструменты.АктивныеДлительныеОперации";
	Если УИ_ПараметрыПриложения[ИмяПараметра] = Неопределено Тогда
		Операции = Новый Структура("Обработка,Список", Ложь, Новый Соответствие);
		УИ_ПараметрыПриложения.Вставить(ИмяПараметра, Операции);
	КонецЕсли;
	Возврат УИ_ПараметрыПриложения[ИмяПараметра];

КонецФункции

Процедура ПроверитьПараметрыОжидатьЗавершение(Знач ДлительнаяОперация, Знач ОповещениеОЗавершении,
	Знач ПараметрыОжидания)

	УИ_ОбщегоНазначенияКлиентСервер.ПроверитьПараметр("УИ_ДлительныеОперацииКлиент.ОжидатьЗавершение",
		"ДлительнаяОперация", ДлительнаяОперация, Тип("Структура"));

	Если ОповещениеОЗавершении <> Неопределено Тогда
		УИ_ОбщегоНазначенияКлиентСервер.ПроверитьПараметр("УИ_ДлительныеОперацииКлиент.ОжидатьЗавершение",
			"ОповещениеОЗавершении", ОповещениеОЗавершении, Тип("ОписаниеОповещения"));
	КонецЕсли;

	Если ПараметрыОжидания <> Неопределено Тогда

		ТипыСвойств = Новый Структура;
		Если ПараметрыОжидания.ФормаВладелец <> Неопределено Тогда
			ТипыСвойств.Вставить("ФормаВладелец", УИ_ОбщегоНазначенияКлиентСервер.ТипУправляемойФормы());
		КонецЕсли;
		ТипыСвойств.Вставить("ТекстСообщения", Тип("Строка"));
		ТипыСвойств.Вставить("ВыводитьОкноОжидания", Тип("Булево"));
		ТипыСвойств.Вставить("ВыводитьПрогрессВыполнения", Тип("Булево"));
		ТипыСвойств.Вставить("ВыводитьСообщения", Тип("Булево"));
		ТипыСвойств.Вставить("Интервал", Тип("Число"));
		ТипыСвойств.Вставить("ОповещениеПользователя", Тип("Структура"));
		ТипыСвойств.Вставить("ПолучатьРезультат", Тип("Булево"));

		УИ_ОбщегоНазначенияКлиентСервер.ПроверитьПараметр("УИ_ДлительныеОперацииКлиент.ОжидатьЗавершение",
			"ПараметрыОжидания", ПараметрыОжидания, Тип("Структура"), ТипыСвойств);
		УИ_ОбщегоНазначенияКлиентСервер.Проверить(ПараметрыОжидания.Интервал = 0 Или ПараметрыОжидания.Интервал >= 1,
			НСтр("ru = 'Параметр ПараметрыОжидания.Интервал должен быть больше или равен 1'"),
			"УИ_ДлительныеОперацииКлиент.ОжидатьЗавершение");
		УИ_ОбщегоНазначенияКлиентСервер.Проверить(Не (ПараметрыОжидания.ОповещениеОПрогрессеВыполнения <> Неопределено
			И ПараметрыОжидания.ВыводитьОкноОжидания), НСтр(
			"ru = 'Если параметр ПараметрыОжидания.ВыводитьОкноОжидания установлен в Истина, то параметр ПараметрыОжидания.ОповещениеОПрогрессеВыполнения не поддерживается'"),
			"УИ_ДлительныеОперацииКлиент.ОжидатьЗавершение");
	КонецЕсли;

КонецПроцедуры

Процедура ПоказатьОповещение(ДлительнаяОперация) Экспорт

	Оповещение = ДлительнаяОперация.ОповещениеПользователя;
	Если Не Оповещение.Показать Тогда
		Возврат;
	КонецЕсли;

	ПоказатьОповещениеПользователя(?(Оповещение.Текст <> Неопределено, Оповещение.Текст, НСтр(
		"ru = 'Действие выполнено'")), Оповещение.НавигационнаяСсылка, Оповещение.Пояснение);

КонецПроцедуры

// Возвращает пустую структуру для параметра ПараметрыОжидания процедуры ДлительныеОперацииКлиент.ОжидатьЗавершение.
//
// Параметры:
//  ФормаВладелец - УправляемаяФорма, Неопределено - форма, из которой вызывается длительная операция.
//
// Возвращаемое значение:
//  Структура              - параметры выполнения задания: 
//   * ФормаВладелец          - УправляемаяФорма, Неопределено - форма, из которой вызывается длительная операция.
//   * ТекстСообщения         - Строка - текст сообщения, выводимый на форме ожидания.
//                                       Если не задан, то выводится "Пожалуйста, подождите...".
//   * ВыводитьОкноОжидания   - Булево - если Истина, то открыть окно ожидания с визуальной индикацией длительной операции. 
//                                       Если используется собственный механизм индикации, то следует указать Ложь.
//   * ВыводитьПрогрессВыполнения - Булево - выводить прогресс выполнения в процентах на форме ожидания.
//   * ОповещениеОПрогрессеВыполнения - ОписаниеОповещения - оповещение, которое периодически вызывается при 
//                                      проверке готовности фонового задания. Параметры процедуры-обработчика оповещения:
//     ** Прогресс - Структура, Неопределено - структура со свойствами или Неопределено, если задание было отменено. Свойства: 
//	     *** Статус               - Строка - "Выполняется", если задание еще не завершилось;
//                                           "Выполнено", если задание было успешно выполнено;
//	                                         "Ошибка", если задание завершено с ошибкой;
//                                           "Отменено", если задание отменено пользователем или администратором.
//	     *** ИдентификаторЗадания - УникальныйИдентификатор - идентификатор запущенного фонового задания.
//	     *** Прогресс             - Структура, Неопределено - результат функции ДлительныеОперации.ПрочитатьПрогресс, 
//                                                            если ВыводитьПрогрессВыполнения = Истина.
//	     *** Сообщения            - ФиксированныйМассив, Неопределено - если ВыводитьСообщения = Истина, массив объектов СообщениеПользователю, 
//                                  очередная порция сообщений, сформированных в процедуре-обработчике длительной операции.
//     ** ДополнительныеПараметры - Произвольный - произвольные данные, переданные в описании оповещения. 
//
//   * ВыводитьСообщения      - Булево - выводить в оповещения о завершении и прогресс сообщения, 
//                                       сформированные в процедуре-обработчике длительной операции.
//   * Интервал               - Число  - интервал в секундах между проверками готовности длительной операции.
//                                       По умолчанию 0 - после каждой проверки интервал увеличивается с 1 до 15 секунд
//                                       с коэффициентом 1.4.
//   * ОповещениеПользователя - Структура - содержит свойства:
//     ** Показать            - Булево - если Истина, то по завершении длительной операции вывести оповещение пользователя.
//     ** Текст               - Строка - текст оповещения пользователя.
//     ** НавигационнаяСсылка - Строка - навигационная ссылка оповещения пользователя.
//     ** Пояснение           - Строка - пояснение оповещения пользователя.
//   
//   * ПолучатьРезультат - Булево - Служебный параметр. Не предназначен для использования.
//
Функция ПараметрыОжидания(ФормаВладелец) Экспорт

	Результат = Новый Структура;
	Результат.Вставить("ФормаВладелец", ФормаВладелец);
	Результат.Вставить("ТекстСообщения", "");
	Результат.Вставить("ВыводитьОкноОжидания", Истина);
	Результат.Вставить("ВыводитьПрогрессВыполнения", Ложь);
	Результат.Вставить("ОповещениеОПрогрессеВыполнения", Неопределено);
	Результат.Вставить("ВыводитьСообщения", Ложь);
	Результат.Вставить("Интервал", 0);
	Результат.Вставить("ПолучатьРезультат", Ложь);

	ОповещениеПользователя = Новый Структура;
	ОповещениеПользователя.Вставить("Показать", Ложь);
	ОповещениеПользователя.Вставить("Текст", Неопределено);
	ОповещениеПользователя.Вставить("НавигационнаяСсылка", Неопределено);
	ОповещениеПользователя.Вставить("Пояснение", Неопределено);
	Результат.Вставить("ОповещениеПользователя", ОповещениеПользователя);

	Возврат Результат;

КонецФункции

// Заполняет структуру параметров новыми расчетными значениями.
// 
// Параметры:
//  ПараметрыОбработчикаОжидания - Структура - заполняется расчетными значениями. 
//
// 
Процедура ОбновитьПараметрыОбработчикаОжидания(ПараметрыОбработчикаОжидания) Экспорт

	ПараметрыОбработчикаОжидания.ТекущийИнтервал = ПараметрыОбработчикаОжидания.ТекущийИнтервал
		* ПараметрыОбработчикаОжидания.КоэффициентУвеличенияИнтервала;
	Если ПараметрыОбработчикаОжидания.ТекущийИнтервал > ПараметрыОбработчикаОжидания.МаксимальныйИнтервал Тогда
		ПараметрыОбработчикаОжидания.ТекущийИнтервал = ПараметрыОбработчикаОжидания.МаксимальныйИнтервал;
	КонецЕсли;

КонецПроцедуры

// Заполняет структуру параметров значениями по умолчанию.
// 
// Параметры:
//  ПараметрыОбработчикаОжидания - Структура - заполняется значениями по умолчанию. 
//
// 
Процедура ИнициализироватьПараметрыОбработчикаОжидания(ПараметрыОбработчикаОжидания) Экспорт

	ПараметрыОбработчикаОжидания = Новый Структура;
	ПараметрыОбработчикаОжидания.Вставить("МинимальныйИнтервал", 1);
	ПараметрыОбработчикаОжидания.Вставить("МаксимальныйИнтервал", 15);
	ПараметрыОбработчикаОжидания.Вставить("ТекущийИнтервал", 1);
	ПараметрыОбработчикаОжидания.Вставить("КоэффициентУвеличенияИнтервала", 1.4);

КонецПроцедуры